﻿/**	lolix_err.h
 *	----	Create Time Stamp	--2007-02-04 13:18:02--
 *-----------------------------------------------------------------------------
 *	Mean	:LoliX 失败返回值
 *	Author	:Nick Shallery	(nicknide@gmail.com)
 *	Version	:1.0.36.50	(2009-09-03 01:57:18)
 *-----------------------------------------------------------------------------
**/	/*YOU HAVE ALL LEFT WITH THIS CODE WHILE YOU KEEP COMMENT IN EVERY COPY.*/


#if			!defined(__LOLIX__LOLIX_ERR__K_IN_G__)
#define		__LOLIX__LOLIX_ERR__K_IN_G__
//==============================================================================
//--------------------------------------------------------------------------

#if			!defined(__LOLIX__TOY__L_X_ASSERT_NICK__K_IN_G__)
	#include	"./toy/lx_assert.h"
#endif	//	!defined(__LOLIX__TOY__L_X_ASSERT_NICK__K_IN_G__)

#if			!defined(__LOLIX__TOY__ALIGN__HPP__NICK__K_IN_G__)
	#include	"./toy/align.hpp"
#endif	//	!defined(__LOLIX__TOY__ALIGN__HPP__NICK__K_IN_G__)


namespace lolix{


//	一个错误的 0~15 16 位表示操作的目标
	enum	ENUM_LOLIX_ERROR_EOT
	{
#define	_LOLIX_EOT_(type, value)	LOLIX_ERR_OBJECT_ ## type = (static_cast<unsigned long>(value)<<0)
	_LOLIX_EOT_(EOT_NULL		, 0x0000),	//	不确定目标的

	_LOLIX_EOT_(EOT_DEVICE		, 0x0001),	//	设备方面
	_LOLIX_EOT_(EOT_ENV			, 0x0002),	//	环境方面
	_LOLIX_EOT_(EOT_FILE		, 0x0003),	//	文件操作方面的
	_LOLIX_EOT_(EOT_INPUT		, 0x0004),	//	设备方面
	_LOLIX_EOT_(EOT_INTERFACE	, 0x0005),	//	接口方面的
	_LOLIX_EOT_(EOT_LOGIC_OPT	, 0x0006),	//	逻辑操作方面
	_LOLIX_EOT_(EOT_MEM			, 0x0007),	//	内存操作方面的
	_LOLIX_EOT_(EOT_OPERATOR	, 0x0008),	//	操作方面
	_LOLIX_EOT_(EOT_PARAM		, 0x0009),	//	参数方面的
	_LOLIX_EOT_(EOT_RANGE		, 0x000a),	//	范围方面
	_LOLIX_EOT_(EOT_RESOURCE	, 0x000b),	//	资源方面的
	_LOLIX_EOT_(EOT_RET_VALUE	, 0x000c),	//	返回值方面
	_LOLIX_EOT_(EOT_RIGHTS		, 0x000d),	//	权限方面的
	_LOLIX_EOT_(EOT_STATE		, 0x000e),	//	状态方面的
	_LOLIX_EOT_(EOT_SYNC		, 0x000f),	//	同步方面的
	_LOLIX_EOT_(EOT_SYS			, 0x0010),	//	系统返回的
	_LOLIX_EOT_(EOT_THIRD_CODE	, 0x0011),	//	第三方调用的
	_LOLIX_EOT_(EOT_TYPE		, 0x0012),	//	类型方面的错误
	_LOLIX_EOT_(EOT_VERSION		, 0x0013),	//	版本方面的

	_LOLIX_EOT_(EOT_ANY			, 0xffff),	//	任意错误
#undef	_LOLIX_EOT_
	};


//	一个错误的 16~24 8 位为表示具体类型
	enum	ENUM_LOLIX_ERROR_EST
	{
#define	_LOLIX_EST_(type, value)	LOLIX_ERR_SUB_TYPE_ ## type = (static_cast<unsigned long>(value)<<16)
	_LOLIX_EST_(EST_NULL			, 0),	//	不确定实质问题

	_LOLIX_EST_(EST_BAD_REDO		, 1),	//	重复操作
	_LOLIX_EST_(EST_BUSY			, 2),	//	忙
	_LOLIX_EST_(EST_INVALID			, 3),	//	无效
	_LOLIX_EST_(EST_LESS			, 4),	//	缺少
	_LOLIX_EST_(EST_LOST			, 5),	//	失败
	_LOLIX_EST_(EST_MORE			, 6),	//	过多
	_LOLIX_EST_(EST_OUT_OF			, 7),	//	越界， 超出
	_LOLIX_EST_(EST_OVERFLOW		, 8),	//	溢出
	_LOLIX_EST_(EST_SEARCH_LOST		, 9),	//	查找失败
	_LOLIX_EST_(EST_UNSUPPORT		,10),	//	不支持
	_LOLIX_EST_(EST_DEPRECATED		,11),	//	不支持

	_LOLIX_EST_(EST_MASK			,0xff),
#undef	_LOLIX_EST_
	};


//	一个错误的 30~31 2 位表示操作的错误类型
	enum	ENUM_LOLIX_ERROR_ESL
	{
#define	_LOLIX_ESL_(type, value)	LOLIX_ERR_SEVERITY_LEVEL_ ## type = (static_cast<unsigned long>(value)<<30)
	_LOLIX_ESL_(ESL_INFO		, 0x0),	//	没有错误
	_LOLIX_ESL_(ESL_WARNING		, 0x1),	//	警告
	_LOLIX_ESL_(ESL_ERROR		, 0x2),	//	错误
	_LOLIX_ESL_(ESL_BAD_ERROR	, 0x3),	//	错误很严重
#undef	_LOLIX_ESL_
	};

	namespace _help{
		template
			< ENUM_LOLIX_ERROR_ESL	_LOLIX_ESL_
			, ENUM_LOLIX_ERROR_EOT	_LOLIX_EOT_
			, ENUM_LOLIX_ERROR_EST	_LOLIX_EST_
			>
		struct _lolix_error_maker
		{
			STATIC_ASSERT( !(_LOLIX_ESL_ & FILL_BITS(unsigned long, 0, 30)) );	//	30位以下为 0
			STATIC_ASSERT( !(_LOLIX_EST_ & FILL_BITS(unsigned long, 0, 16)) && !(_LOLIX_EST_ & FILL_BITS(unsigned long long, 16+8, 32)) );
			STATIC_ASSERT( !(_LOLIX_EOT_ & FILL_BITS(unsigned long long, 16, 32)) );
			enum{ rtv = _LOLIX_ESL_ + _LOLIX_EOT_ + _LOLIX_EST_ };
		};
	}


#define	LOLIX_MAKE_ERROR(ESL, EOT, EST)					\
	(LOLIX_RETNV)lolix::_help::_lolix_error_maker		\
			< LOLIX_ERR_SEVERITY_LEVEL_ ## ESL			\
			, LOLIX_ERR_OBJECT_ ## EOT					\
			, LOLIX_ERR_SUB_TYPE_ ## EST				\
			>::rtv


#define	DEFINE_LOLIX_ERROR(ESL, EOT, EST, ENM, comment)			\
	/*const	LOLIX_RETNV	*/ENM	=	LOLIX_MAKE_ERROR(ESL, EOT, EST),

	enum LOLIX_RETNV
	{
		#include	"./lolix_err.inl"
	};

#define	DEFINE_LOLIX_ERROR(ESL, EOT, EST, ENM, comment)			case ENM: *out_ptr = L## #comment;break;
	LOLIX_INLINE_CALL void lolix_retnv_comment(LOLIX_RETNV rtv, const wchar_t** out_ptr)
	{
		switch ( rtv )
		{
		#include	"./lolix_err.inl"
		default:*out_ptr = L"UNKNOW LOLIX_RETNV";break;
		}
	}

#define	DEFINE_LOLIX_ERROR(ESL, EOT, EST, ENM, comment)			case ENM: *out_ptr = #comment;break;
	LOLIX_INLINE_CALL void lolix_retnv_comment(LOLIX_RETNV rtv, const char** out_ptr)
	{
		switch ( rtv )
		{
		#include	"./lolix_err.inl"
		default: *out_ptr = "UNKNOW LOLIX_RETNV";break;
		}
	}

#define	DEFINE_LOLIX_ERROR(ESL, EOT, EST, ENM, comment)			case ENM: *out_ptr = L## #ENM;break;
	LOLIX_INLINE_CALL void lolix_retnv_code(LOLIX_RETNV rtv, const wchar_t** out_ptr)
	{
		switch ( rtv )
		{
		#include	"./lolix_err.inl"
		default:*out_ptr = L"UNKNOW LOLIX_RETNV";break;
		}
	}

#define	DEFINE_LOLIX_ERROR(ESL, EOT, EST, ENM, comment)			case ENM: *out_ptr = #ENM;break;
	LOLIX_INLINE_CALL void lolix_retnv_code(LOLIX_RETNV rtv, const char** out_ptr)
	{
		switch ( rtv )
		{
		#include	"./lolix_err.inl"
		default: *out_ptr = "UNKNOW LOLIX_RETNV";break;
		}
	}
}


#define	LOLIX_DEF__LOLIX_IS_ERROR(lx_retnv)	(((::lolix::LOLIX_RETNV(lx_retnv))>>31)?true:false)
#define	LOLIX_DEF__LOLIX_IS_WARNING(lx_rtv)	(((::lolix::LOLIX_RETNV(lx_rtv))&(1<<30))?true:false)

#if			LOLIX_CFG__IS_USE_ASSERT

	#if			1 || LOLIX_CFG__PLATFORM_WINDOWS && LOLIX_CFG__SIZE_TYPE_BYTE_SIZE == 4
		#define	__AT_DEFINE_TEMPLATE__LINE__
		#define	__AT_DEFINE_PARAM_LINE__		, int LINE
		#define	__AT_USE_TEMPLATE__LINE__
		#define	__AT_USE_PARAM_LINE__			, LINE
		#define	LOLIX_DEF__LOLIX_CHECK_ERROR(lx_retnv)		::lolix::__Lolix_check_error<__COUNTER__>(lx_retnv, #lx_retnv, __FILE__, __FUNCTION__, __LINE__)
		#define	LOLIX_DEF__LOLIX_RETURN_ERROR(lx_retnv)		::lolix::__Lolix_return_error<__COUNTER__>(lx_retnv, #lx_retnv, __FILE__, __FUNCTION__, __LINE__)
	#else	//	LOLIX_CFG__PLATFORM_WINDOWS && LOLIX_CFG__SIZE_TYPE_BYTE_SIZE == 4
		#define	__AT_DEFINE_TEMPLATE__LINE__	, int LINE
		#define	__AT_DEFINE_PARAM_LINE__
		#define	__AT_USE_TEMPLATE__LINE__		, LINE
		#define	__AT_USE_PARAM_LINE__
		#define	LOLIX_DEF__LOLIX_CHECK_ERROR(lx_retnv)		::lolix::__Lolix_check_error<__COUNTER__, __LINE__>(lx_retnv, #lx_retnv, __FILE__, __FUNCTION__)
		#define	LOLIX_DEF__LOLIX_RETURN_ERROR(lx_retnv)		::lolix::__Lolix_return_error<__COUNTER__, __LINE__>(lx_retnv, #lx_retnv, __FILE__, __FUNCTION__)
	#endif	//	LOLIX_CFG__PLATFORM_WINDOWS && LOLIX_CFG__SIZE_TYPE_BYTE_SIZE == 4

	namespace	lolix
	{
		template<int COUNT __AT_DEFINE_TEMPLATE__LINE__>
		LOLIX_INLINE_CALL	bool	__Lolix_check_error(LOLIX_RETNV in_rtv, const char* str, const char* file_name, const char* func_name __AT_DEFINE_PARAM_LINE__)
		{
			static ::lolix::toy::lx_assert::lolix_assert_class oname(file_name, func_name, LINE, 2);
			const char* error_comment;
			lolix_retnv_comment(in_rtv, &error_comment);
			const char* error_code;
			lolix_retnv_code(in_rtv, &error_code);
			oname.do_assert(!LOLIX_DEF__LOLIX_IS_ERROR(in_rtv), "%s\nLOLIX_RETNV(value):0x%I32x\nLOLIX_RETNV(code):%s\nLOLIX_RETNV(comment):%s", str, in_rtv, error_code, error_comment);
			return LOLIX_DEF__LOLIX_IS_ERROR(in_rtv)?true:false;
		}
		template<int COUNT __AT_DEFINE_TEMPLATE__LINE__>
		LOLIX_INLINE_CALL	bool	__Lolix_check_error(LOLIX_RETNV in_rtv, const wchar_t* str, const wchar_t* file_name, const wchar_t* func_name __AT_DEFINE_PARAM_LINE__)
		{
			static ::lolix::toy::lx_assert::lolix_assert_class oname(file_name, func_name, LINE, 2);
			const wchar_t* error_comment;
			lolix_retnv_comment(in_rtv, &error_comment);
			const wchar_t* error_code;
			lolix_retnv_code(in_rtv, &error_code);
			oname.do_assert(!LOLIX_DEF__LOLIX_IS_ERROR(in_rtv), L"%s\nLOLIX_RETNV(value):0x%I32x\nLOLIX_RETNV(code):%s\nLOLIX_RETNV(comment):%s", str, in_rtv, error_comment, str);
			return LOLIX_DEF__LOLIX_IS_ERROR(in_rtv)?true:false;
		}
		template<int COUNT __AT_DEFINE_TEMPLATE__LINE__>
		LOLIX_INLINE_CALL	LOLIX_RETNV	__Lolix_return_error(LOLIX_RETNV in_rtv, const char* str, const char* file_name, const char* func_name __AT_DEFINE_PARAM_LINE__)
		{
			__Lolix_check_error<COUNT __AT_USE_TEMPLATE__LINE__>(in_rtv, str, file_name, func_name __AT_USE_PARAM_LINE__);
			return in_rtv;
		}
		template<int COUNT __AT_DEFINE_TEMPLATE__LINE__>
		LOLIX_INLINE_CALL	LOLIX_RETNV	__Lolix_return_error(LOLIX_RETNV in_rtv, const wchar_t* str, const wchar_t* file_name, const wchar_t* func_name __AT_DEFINE_PARAM_LINE__)
		{
			__Lolix_check_error<COUNT __AT_USE_TEMPLATE__LINE__>(in_rtv, str, file_name, func_name __AT_USE_PARAM_LINE__);
			return in_rtv;
		}

		struct	LOLIX_NO_ERROR
		{
			LOLIX_INLINE_CALL	LOLIX_NO_ERROR(LOLIX_RETNV rtv)
			{
				LOLIX_DEF__LOLIX_CHECK_ERROR(rtv);
			}
		private:
			CANNT_COPY_LOLI;
		};
	}

#else	//	LOLIX_CFG__IS_USE_ASSERT
	#define	LOLIX_DEF__LOLIX_CHECK_ERROR			LOLIX_DEF__LOLIX_IS_ERROR
	#define	LOLIX_DEF__LOLIX_RETURN_ERROR(lx_retnv)	lx_retnv

	namespace lolix
	{
		struct	LOLIX_NO_ERROR
		{
			LOLIX_INLINE_CALL	LOLIX_NO_ERROR(LOLIX_RETNV){}
		private:
			CANNT_COPY_LOLI;
		};
	}

#endif	//	LOLIX_CFG__IS_USE_ASSERT


//--------------------------------------------------------------------------
//==============================================================================
#endif	//	!defined(__LOLIX__LOLIX_ERR__K_IN_G__)
